import os
import time
import uuid

from flask import Blueprint, session, render_template, request, current_app, redirect

from db import db
from model.HouseInfo import HouseInfo
from model.User import User
from pred.regress import getPredict
from utils.errorResponse import errorResponse
from utils.getPageData import *
from utils.verify_rule import file_suffix, file_is_img, str_is_blank

# 蓝图，类似于spring boot中的controller
page_bp = Blueprint(
    "page",
    __name__,
    url_prefix="/page",
    template_folder="templates",
    static_folder="static",
)

# 定义一个字典，用于将数字映射为中文
num_map_chinese = {
    "": "",
    "1": "一",
    "2": "二",
    "3": "三",
    "4": "四",
    "5": "五",
    "6": "六",
    "7": "七",
    "8": "八",
    "9": "九",
    "10": "十",
    "11": "十一",
    "12": "十二",
    "13": "十三",
    "14": "十四",
    "15": "十五",
    "16": "十六",
    "17": "十七",
    "18": "十八",
    "19": "十九",
}


@page_bp.route("/home")
def home():
    """
    首页
    :return:
    """
    username = session.get("username")
    user = User.query.filter_by(username=username).first()
    last_login = user.last_login
    email = user.email
    average_price_map = echartsData(getHouseProvinceAvgPriceChinaMapData())
    tags = getHouseTagsDta()
    city_num_pie = echartsData(getHouseRadarData())
    return render_template(
        "index.html",
        username=username,
        average_price_map=average_price_map,
        size=tags["size"],
        max_price=tags["max_price"],
        house_type=tags["house_type"],
        status_type=tags["status_type"],
        city_num_pie=city_num_pie,
        last_login=last_login,
        email=email,
    )


@page_bp.route("/search", methods=["GET", "POST"])
def search():
    """
    搜索页面
    :return:
    """
    username = session.get("username")
    if request.method == "GET":
        citys = queryHouseDataField("city")
        imgs = queryHouseDataField("city,cover", 100)
    else:
        keyword = request.form.get("keyword")
        citys = searchData(keyword, "city")
        imgs = searchData(keyword, "city,cover")
    return render_template("search.html", username=username, citys=citys, imgs=imgs)


@page_bp.route("/table", methods=["GET", "POST"])
def table():
    username = session.get("username")
    house_info_list = HouseInfo2Dict(HouseInfo.query.all()[:100])

    return render_template(
        "table.html", username=username, house_info_list=house_info_list
    )


@page_bp.route("/detail", methods=["GET", "POST"])
def detail():
    username = session.get("username")
    house_id = request.args.get("id")
    house_info = HouseInfo2Dict2(HouseInfo.query.filter_by(id=house_id).first())

    return render_template("detail.html", username=username, house_info=house_info)


@page_bp.route("/edit", methods=["GET", "POST"])
def edit():
    username = session.get("username")
    house_id = request.args.get("id")
    if request.method == "GET":
        house_info = HouseInfo2Dict3(HouseInfo.query.filter_by(id=house_id).first())
        return render_template(
            "editHouse.html", username=username, house_info=house_info
        )
    else:
        cover = request.files.get("cover")
        filetype = cover.content_type.split("/")[1]
        cover_url = ""
        if not file_is_img(filetype):
            return errorResponse("图片格式不正确！")
            filename = uuid.uuid4().hex + "." + file_suffix(cover.filename)
            save_path = os.path.join(current_app.config["UPLOAD_FOLDER"], filename)
            cover.save(save_path)
            cover_url = r"http://localhost:5210/static/upload/" + filename

        title = request.form.get("title")
        city = request.form.get("city")
        region = request.form.get("region")
        address = request.form.get("address")
        rooms_desc = request.form.get("rooms_desc")
        area_range = request.form.get("area_range")
        total_price_range = request.form.get("total_price_range")
        prices = request.form.get("prices")
        house_decoration = request.form.get("house_decoration")
        house_type = request.form.get("house_type")
        tags = request.form.get("tags")

        editHouseData(
            {
                "id": house_id,
                "title": title.strip(),
                "city": city.strip(),
                "region": region.strip(),
                "address": address.strip(),
                "rooms_desc": rooms_desc.strip(),
                "area_range": area_range.strip(),
                "total_price_range": total_price_range.strip(),
                "prices": prices.strip(),
                "house_decoration": house_decoration.strip(),
                "house_type": house_type.strip(),
                "tags": tags.strip(),
                "cover": cover_url,
            }
        )

        return redirect("/page/table")


@page_bp.route("/addHouse", methods=["GET", "POST"])
def addHouse():
    username = session.get("username")
    if request.method == "GET":
        return render_template(
            "addHouse.html",
            username=username,
        )
    else:
        cover = request.files.get("cover")
        filetype = cover.content_type.split("/")[1]
        if not file_is_img(filetype):
            return errorResponse("图片格式不正确！")
        filename = uuid.uuid4().hex + "." + file_suffix(cover.filename)
        save_path = os.path.join(current_app.config["UPLOAD_FOLDER"], filename)
        cover.save(save_path)

        title = request.form.get("title")
        city = request.form.get("city")
        region = request.form.get("region")
        address = request.form.get("address")
        rooms_desc = request.form.get("rooms_desc")
        area_range = request.form.get("area_range")
        total_price_range = request.form.get("total_price_range")
        prices = request.form.get("prices")
        house_decoration = request.form.get("house_decoration")
        house_type = request.form.get("house_type")
        tags = request.form.get("tags")

        addHouseData(
            {
                "title": title.strip(),
                "city": city.strip(),
                "region": region.strip(),
                "address": address.strip(),
                "rooms_desc": rooms_desc.strip(),
                "area_range": area_range.strip(),
                "total_price_range": total_price_range.strip(),
                "prices": prices.strip(),
                "house_decoration": house_decoration.strip(),
                "house_type": house_type.strip(),
                "tags": tags.strip(),
                "cover": r"http://localhost:5210/static/upload/" + filename,
            }
        )

        return redirect("/page/table")


@page_bp.route("/delete", methods=["GET", "POST"])
def delete():
    house_id = request.args.get("id")
    deleteHouseData(house_id)
    return redirect("/page/table")


def HouseInfo2Dict(house_info_list):
    """
    用于将HouseInfo对象列表转化为格式化后的字典列表
    :param house_info_list:
    :return:
    """
    house_info_dict_list = []
    for house_info in house_info_list:
        house_info_dict_list.append(
            {
                "id": house_info.id,
                "title": house_info.title,
                "cover": house_info.cover,
                "city": house_info.city,
                "region": house_info.region,
                "address": house_info.address,
                "rooms_desc": "/ ".join(
                    [room + "室" for room in json.loads(house_info.rooms_desc)]
                ),
                "area_range": "~".join(json.loads(house_info.area_range)) + " m²",
                "all_ready": house_info.all_ready,
                "prices": house_info.prices,
                "house_decoration": house_info.house_decoration,
                "company": house_info.company,
                "house_type": house_info.house_type,
                "on_time": house_info.on_time,
                "open_date": house_info.open_date,
                "tags": json.loads(house_info.tags),
                "total_price_range": "~".join(json.loads(house_info.total_price_range)),
                "sale_status": house_info.sale_status,
                "detail_url": house_info.detail_url,
            }
        )
    return house_info_dict_list


def HouseInfo2Dict2(house_info):
    """
    用于将HouseInfo对象转化为格式化后的字典
    :param house_info:
    :return:
    """
    return {
        "id": house_info.id,
        "title": house_info.title,
        "cover": house_info.cover,
        "city": house_info.city,
        "region": house_info.region,
        "address": house_info.address,
        "rooms_desc": " / ".join(
            [
                num_map_chinese[str(room)] + "居室"
                for room in json.loads(house_info.rooms_desc)
            ]
        ),
        "area_range": "~".join(json.loads(house_info.area_range)) + " m²",
        "all_ready": house_info.all_ready,
        "prices": house_info.prices,
        "house_decoration": house_info.house_decoration,
        "company": house_info.company,
        "house_type": house_info.house_type,
        "on_time": house_info.on_time,
        "open_date": house_info.open_date,
        "tags": json.loads(house_info.tags),
        "total_price_range": "~".join(json.loads(house_info.total_price_range)),
        "sale_status": house_info.sale_status,
        "detail_url": house_info.detail_url,
    }


def HouseInfo2Dict3(house_info):
    """
    用于将HouseInfo对象转化为未进行格式化的字典
    :param house_info:
    :return:
    """
    return {
        "id": house_info.id,
        "title": house_info.title,
        "cover": house_info.cover,
        "city": house_info.city,
        "region": house_info.region,
        "address": house_info.address,
        "rooms_desc": json.loads(house_info.rooms_desc),
        "area_range": json.loads(house_info.area_range),
        "all_ready": house_info.all_ready,
        "prices": house_info.prices,
        "house_decoration": house_info.house_decoration,
        "company": house_info.company,
        "house_type": house_info.house_type,
        "on_time": house_info.on_time,
        "open_date": house_info.open_date,
        "tags": json.loads(house_info.tags),
        "total_price_range": json.loads(house_info.total_price_range),
        "sale_status": house_info.sale_status,
        "detail_url": house_info.detail_url,
    }


def addHouseData(house_info):
    """
    添加房源数据
    :param house_info:
    :return:
    """
    print(house_info)
    title = house_info.get("title")
    city = house_info.get("city")
    region = house_info.get("region")
    address = house_info.get("address")
    rooms_desc = json.dumps(house_info.get("rooms_desc").split(","), ensure_ascii=False)
    area_range = json.dumps(house_info.get("area_range").split(","), ensure_ascii=False)
    total_price_range = json.dumps(
        house_info.get("total_price_range").split(","), ensure_ascii=False
    )
    prices = house_info.get("prices")
    house_decoration = house_info.get("house_decoration")
    house_type = house_info.get("house_type")
    tags = json.dumps(house_info.get("tags").split(","), ensure_ascii=False)
    cover = house_info.get("cover")
    new_house = HouseInfo(
        title=title,
        city=city,
        region=region,
        address=address,
        rooms_desc=rooms_desc,
        area_range=area_range,
        total_price_range=total_price_range,
        prices=prices,
        house_decoration=house_decoration,
        house_type=house_type,
        tags=tags,
        cover=cover,
        on_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
    )
    db.session.add(new_house)
    db.session.commit()


def editHouseData(new_house_info):
    """
    编辑房源数据
    :param new_house_info:
    :return:
    """
    # print(new_house_info)
    house_id = new_house_info.get("id")
    house_info = HouseInfo.query.filter_by(id=house_id).first()
    # print(house_info)
    title = new_house_info.get("title")
    city = new_house_info.get("city")
    region = new_house_info.get("region")
    address = new_house_info.get("address")
    rooms_desc = json.dumps(
        new_house_info.get("rooms_desc").split(","), ensure_ascii=False
    )
    area_range = json.dumps(
        new_house_info.get("area_range").split(","), ensure_ascii=False
    )
    total_price_range = json.dumps(
        new_house_info.get("total_price_range").split(","), ensure_ascii=False
    )
    prices = new_house_info.get("prices")
    house_decoration = new_house_info.get("house_decoration")
    house_type = new_house_info.get("house_type")
    tags = json.dumps(new_house_info.get("tags").split(","), ensure_ascii=False)
    cover = new_house_info.get("cover")
    house_info.title = title
    house_info.city = city
    house_info.region = region
    house_info.address = address
    house_info.rooms_desc = rooms_desc
    house_info.total_price_range = total_price_range
    house_info.area_range = area_range
    house_info.prices = prices
    house_info.house_decoration = house_decoration
    house_info.house_type = house_type
    house_info.tags = tags
    if not str_is_blank(cover):
        house_info.cover = cover
    db.session.commit()


def deleteHouseData(house_id):
    """
    删除房源数据
    :param house_id:
    :return:
    """
    house_info = HouseInfo.query.filter_by(id=house_id).first()
    db.session.delete(house_info)
    db.session.commit()


@page_bp.route("/price_char")
def price_char():
    username = session.get("username")
    citys = queryHouseDataField("city")
    city = request.args.get("default_city")
    default_city = city if city else citys[0]
    if city:
        house_info_list = (
            HouseInfo.query.filter_by(city=city)
            .with_entities(
                HouseInfo.prices, HouseInfo.total_price_range, HouseInfo.open_date
            )
            .all()
        )
    else:
        house_info_list = HouseInfo.query.with_entities(
            HouseInfo.prices, HouseInfo.total_price_range, HouseInfo.open_date
        ).all()
    X, Y = getPriceCharData(house_info_list)
    X_2, Y_2 = getDatePriceData(house_info_list)
    total_price_range = getTotalPriceData(house_info_list)
    return render_template(
        "price_char.html",
        username=username,
        citys=citys,
        default_city=default_city,
        X=X,
        Y=Y,
        X_2=X_2,
        Y_2=Y_2,
        total_price_range=total_price_range,
    )


def getPriceCharData(house_info_list):
    X = [
        "<=2000",
        "2000-4000",
        "4000-6000",
        "6000-8000",
        "8000-10000",
        "10000-12000",
        "12000-15000",
        "15000-20000",
        ">=20000",
    ]
    Y = [0 for _ in range(len(X))]
    for h in house_info_list:
        price = int(h.prices)
        if price <= 2000:
            Y[0] += 1
        elif price <= 4000:
            Y[1] += 1
        elif price <= 6000:
            Y[2] += 1
        elif price <= 8000:
            Y[3] += 1
        elif price <= 10000:
            Y[4] += 1
        elif price <= 12000:
            Y[5] += 1
        elif price <= 15000:
            Y[6] += 1
        elif price <= 20000:
            Y[7] += 1
        else:
            Y[8] += 1
    return X, Y


def getDatePriceData(house_info_list):
    X = [house_info.open_date for house_info in house_info_list]
    Y = [int(house_info.prices) for house_info in house_info_list]
    return X, Y


def getTotalPriceData(house_info_list):
    data = []
    for house_info in house_info_list:
        total_price_range = json.loads(house_info.total_price_range)
        data.append(total_price_range)
    return data


@page_bp.route("/detail_char")
def detail_char():
    house_info_list = HouseInfo.query.with_entities(
        HouseInfo.rooms_desc, HouseInfo.area_range
    ).all()
    treemapData = getRoomDescData(house_info_list)

    X, Y1 = getDetailCharData(house_info_list, "small")
    X, Y2 = getDetailCharData(house_info_list, "big")
    return render_template(
        "detail_char.html", treemapData=treemapData, X=X, Y1=Y1, Y2=Y2
    )


def getRoomDescData(house_info_list):
    room_desc_cnt = Counter()
    for house_info in house_info_list:
        rooms = json.loads(house_info.rooms_desc)
        if rooms is None:
            continue
        for room in rooms:
            if str_is_blank(room) or int(room) > 19:
                continue
            room_desc_cnt[num_map_chinese[str(room)] + "居室"] += 1
    data = []

    for room, cnt in room_desc_cnt.items():
        data.append({"name": room, "value": cnt})
    return data


def getDetailCharData(house_info_list, defaultType):
    X = [
        "0-20",
        "20-40",
        "40-60",
        "60-80",
        "80-100",
        "100-120",
        "120-150",
        "150-200",
        ">=200",
    ]
    Y = [0 for _ in range(len(X))]
    for house_info in house_info_list:
        area_range = json.loads(house_info.area_range)
        if area_range is None or len(area_range) != 2:
            continue
        if defaultType == "small":
            area = float(area_range[0])
        else:
            area = float(area_range[1])
        if area <= 20:
            Y[0] += 1
        elif area <= 40:
            Y[1] += 1
        elif area <= 60:
            Y[2] += 1
        elif area <= 80:
            Y[3] += 1
        elif area <= 100:
            Y[4] += 1
        elif area <= 120:
            Y[5] += 1
        elif area <= 150:
            Y[6] += 1
        elif area <= 200:
            Y[7] += 1
        else:
            Y[8] += 1

    return X, Y


@page_bp.route("/type_char")
def type_char():
    username = session.get("username")
    citys = queryHouseDataField("city")
    city = request.args.get("default_city")
    default_city = city if city else citys[0]
    decoration_cnt = echartsData(
        queryHouseDataFieldCnt("house_decoration", "*", f"city='{default_city}'")
    )
    house_type_cnt = echartsData(
        queryHouseDataFieldCnt("house_type", "*", f"city='{default_city}'")
    )

    return render_template(
        "type_char.html",
        username=username,
        citys=citys,
        default_city=default_city,
        decoration_cnt=decoration_cnt,
        house_type_cnt=house_type_cnt,
    )


@page_bp.route("/price_predict", methods=["GET", "POST"])
def price_predict():
    username = session.get("username")
    citys = queryHouseDataField("city")
    predict_price = 0
    if request.method == "POST":
        city = request.form.get("checkCity")
        rooms_desc = request.form.get("rooms_desc")
        area_range = request.form.get("area_range")
        house_type = request.form.get("house_type")
        sale_status = request.form.get("sale_status")
        predict_price = getPredict(
            city, rooms_desc, area_range, house_type, sale_status
        )
    return render_template(
        "price_predict.html",
        username=username,
        citys=citys,
        predict_price=predict_price,
    )


@page_bp.route("/data_export")
def data_export():
    return render_template("data_export.html")
